package units;


import pheromoneMap.PheromoneMap;
import pheromoneMap.PheromoneType;
import base.ProxyBot;
import base.WargusUnit;

public class AntUnit {
	private final static double RANDOM_MOVEMENT_THRESHOLD = 0.05;
	protected final static double DEATH_THRESHOLD = 0.5;
	protected ProxyBot proxyBot;
	protected PheromoneMap pheromoneMap;
	protected WargusUnit unit;
	private boolean isDead = false;
	
	public AntUnit(ProxyBot proxyBot, PheromoneMap pheromoneMap, WargusUnit wargusUnit) {
		this.proxyBot = proxyBot;
		this.pheromoneMap = pheromoneMap;
		this.unit = wargusUnit;
	}

	public void updateState() {
		if (unit.IsDead() && !isDead) {
			this.pheromoneMap.placeAttractionPheromone(unit.getLocX(), unit.getLocY(), PheromoneType.DEATH, 100);
			isDead = true;
		}
	}
	
	public void move() {
	}
	
	public String getState() {
		return "null";
	}
	
	public void layPheromone( PheromoneType pheromoneType, double strength, double direction ) {
		pheromoneMap.placePheromone( unit.getLocX(), unit.getLocY(), pheromoneType,
				strength, direction );
	}
	
	public void moveRandom() {
		proxyBot.move_random(unit.getUnitID());
	}
	
	public void moveTrail( PheromoneType pheromoneType ) {
		double magnitude = pheromoneMap.getMagnitude( unit.getLocX(), unit.getLocY(), pheromoneType );
		double heading = pheromoneMap.getDirection(	unit.getLocX(), unit.getLocY(), pheromoneType );
		
		if(Math.random() > RANDOM_MOVEMENT_THRESHOLD){//checkProbability( magnitude, RANDOM_MOVEMENT_THRESHOLD ) ) {
			int x = (int) (1 * Math.round(Math.cos(heading)));
			int y = (int) (1 * Math.round(Math.sin(heading)));
	
			int x_map = unit.getLocX() + x;
			int y_map = unit.getLocY() + y;
	
			boolean checkMap = proxyBot.CheckMapCell( x_map, y_map);
	
			if (!checkMap)
			{
				int move_x = 4*x;
				int move_y = 4*y;
				
				if(move_x +  unit.getLocX() < 0)
					move_x = 0 - unit.getLocX();
				else if(move_x + unit.getLocX() > proxyBot.GetMapWidth())
					move_x = proxyBot.GetMapWidth() - 1 - unit.getLocX();
				
				if(move_y + unit.getLocY()< 0)
					move_y = 0 - unit.getLocY();
				else if(move_y + unit.getLocY() > proxyBot.GetMapLength())
					move_y = proxyBot.GetMapLength() - 1 - unit.getLocY();
				
				
				proxyBot.move(unit.getUnitID(), move_x, move_y, true);
			}
			else
				moveRandom();
		} else {
			moveRandom();
		}
	}

	public void moveTrail( PheromoneType pheromoneType1 , PheromoneType pheromoneType2) {
		double magnitude1 = pheromoneMap.getMagnitude( unit.getLocX(), unit.getLocY(), pheromoneType1 );
		double heading1 = pheromoneMap.getDirection(	unit.getLocX(), unit.getLocY(), pheromoneType1 );
		
		double magnitude2 = pheromoneMap.getMagnitude( unit.getLocX(), unit.getLocY(), pheromoneType2 );
		double heading2 = pheromoneMap.getDirection(	unit.getLocX(), unit.getLocY(), pheromoneType2 );
		
		double heading; 
		
		if(magnitude2 > 0.5)
			heading = (heading1 + heading2) / 2.0;
		else
			heading = heading1;
		
		if(true){//Math.random() > RANDOM_MOVEMENT_THRESHOLD){//checkProbability( magnitude, RANDOM_MOVEMENT_THRESHOLD ) ) {
			int x = (int) (1 * Math.round(Math.cos(heading)));
			int y = (int) (1 * Math.round(Math.sin(heading)));
	
			int x_map = unit.getLocX() + x;
			int y_map = unit.getLocY() + y;
	
			boolean checkMap = proxyBot.CheckMapCell( x_map, y_map);
	
			if (!checkMap)
			{
				int move_x = 4*x;
				int move_y = 4*y;
				
				if(move_x +  unit.getLocX() < 0)
					move_x = 0 - unit.getLocX();
				else if(move_x + unit.getLocX() > proxyBot.GetMapWidth())
					move_x = proxyBot.GetMapWidth() - 1 - unit.getLocX();
				
				if(move_y + unit.getLocY()< 0)
					move_y = 0 - unit.getLocY();
				else if(move_y + unit.getLocY() > proxyBot.GetMapLength())
					move_y = proxyBot.GetMapLength() - 1 - unit.getLocY();
				
				
				proxyBot.move(unit.getUnitID(), move_x, move_y, true);
			}
			else
				moveRandom();
		} else {
			moveRandom();
		}
	}

	public void moveTrailReverse( PheromoneType pheromoneType ) {
		double magnitude = pheromoneMap.getMagnitude( unit.getLocX(), unit.getLocY(), pheromoneType );
		double heading = pheromoneMap.getDirection(	unit.getLocX(), unit.getLocY(), pheromoneType ) + (Math.PI / 2);
		
		if( checkProbability( magnitude, RANDOM_MOVEMENT_THRESHOLD ) ) {
			int x = (int) (1 * Math.round(Math.cos(heading)));
			int y = (int) (1 * Math.round(Math.sin(heading)));
	
			int x_map = unit.getLocX() + x;
			int y_map = unit.getLocY() + y;
	
			boolean checkMap = proxyBot.CheckMapCell( x_map, y_map);
	
			if (!checkMap)
			{
				int move_x = 4*x;
				int move_y = 4*y;
				
				if(move_x +  unit.getLocX() < 0)
					move_x = 0 - unit.getLocX();
				else if(move_x + unit.getLocX() > proxyBot.GetMapWidth())
					move_x = proxyBot.GetMapWidth() - 1 - unit.getLocX();
				
				if(move_y + unit.getLocY()< 0)
					move_y = 0 - unit.getLocY();
				else if(move_y + unit.getLocY() > proxyBot.GetMapLength())
					move_y = proxyBot.GetMapLength() - 1 - unit.getLocY();
				
				
				proxyBot.move(unit.getUnitID(), move_x, move_y, true);
			}
			else
				moveRandom();
		} else {
			moveRandom();
		}
	}

	public void moveTrailSticky( PheromoneType pheromoneType ) {
		double magnitude = pheromoneMap.getMagnitude( unit.getLocX(), unit.getLocY(), pheromoneType );
		double heading = pheromoneMap.getDirection(	unit.getLocX(), unit.getLocY(), pheromoneType );
		
		if( checkProbability( magnitude, RANDOM_MOVEMENT_THRESHOLD ) ) {
			int x = (int) (1 * Math.round(Math.cos(heading)));
			int y = (int) (1 * Math.round(Math.sin(heading)));
	
			int x_map = unit.getLocX() + x;
			int y_map = unit.getLocY() + y;
	
			boolean checkMap = proxyBot.CheckMapCell( x_map, y_map);
	
			if (!checkMap)
			{
				int move_x = 4*x;
				int move_y = 4*y;
				
				if(move_x +  unit.getLocX() < 0)
					move_x = 0 - unit.getLocX();
				else if(move_x + unit.getLocX() > proxyBot.GetMapWidth())
					move_x = proxyBot.GetMapWidth() - 1 - unit.getLocX();
				
				if(move_y + unit.getLocY()< 0)
					move_y = 0 - unit.getLocY();
				else if(move_y + unit.getLocY() > proxyBot.GetMapLength())
					move_y = proxyBot.GetMapLength() - 1 - unit.getLocY();
				
				
				proxyBot.move(unit.getUnitID(), move_x, move_y, true);
			}
		}
	}

	public void moveTrail2( PheromoneType pheromoneType ) {
		double magnitude = pheromoneMap.getMagnitude( unit.getLocX(), unit.getLocY(), pheromoneType );
		double heading = pheromoneMap.getDirection(	unit.getLocX(), unit.getLocY(), pheromoneType );
		
		if(true){//checkProbability( magnitude, RANDOM_MOVEMENT_THRESHOLD ) ) {
			int x = (int) (1 * Math.round(Math.cos(heading)));
			int y = (int) (1 * Math.round(Math.sin(heading)));
	
			int x_map = unit.getLocX() + x;
			int y_map = unit.getLocY() + y;
	
			boolean checkMap = proxyBot.CheckMapCell( x_map, y_map);
	
			if (!checkMap)
			{
				int move_x = 4*x;
				int move_y = 4*y;
				
				if(move_x +  unit.getLocX() < 0)
					move_x = 0 - unit.getLocX();
				else if(move_x + unit.getLocX() > proxyBot.GetMapWidth())
					move_x = proxyBot.GetMapWidth() - 1 - unit.getLocX();
				
				if(move_y + unit.getLocY()< 0)
					move_y = 0 - unit.getLocY();
				else if(move_y + unit.getLocY() > proxyBot.GetMapLength())
					move_y = proxyBot.GetMapLength() - 1 - unit.getLocY();
				
				
				proxyBot.move(unit.getUnitID(), move_x, move_y, true);
			}
		}
		else
			moveRandom();
	}
	/**
	 * @return the unit
	 */
	public WargusUnit getUnit() {
		return unit;
	}

	/**
	 * @param unit the unit to set
	 */
	public void setUnit(WargusUnit unit) {
		this.unit = unit;
	}
	
	public static boolean checkProbability( double magnitude, double threshold ) {
		boolean returnVal;
		
		double threshold2 = threshold * 2;
		double threshold3 = threshold * 3;
		
		double probability;
		if( magnitude < threshold )
			probability = 0.5 * (magnitude / threshold);
		else if( magnitude < threshold2 )
			probability = 0.5 + (0.35 * ((magnitude - threshold) / (threshold2 - threshold)));
		else if( magnitude < threshold3 )
			probability = 0.85 + (0.14 * ((magnitude - threshold2) / (threshold3 - threshold2)));
		else
			probability = 0.99 + (0.01 * ((magnitude - threshold3) / (10 - threshold3)));
		
		if( Math.random() < probability )
			returnVal = true;
		else
			returnVal = false;
		
		return returnVal;
	}
}